package com.xzy.bbb.postprocessor;

import com.xzy.bbb.bean.CustomBean;
import com.xzy.bbb.bean.ExampleBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationScopeMetadataResolver;
import org.springframework.context.annotation.ScopeMetadata;
import org.springframework.context.annotation.ScopeMetadataResolver;

/**
 * 利用BeanFactoryPostProcessor可以实现下列功能：
 * <ol>
 *     <li>动态修改Bean定义的属性值
 *     <li>替换Bean的实现类
 *     <li>根据条件移除或添加Bean的定义
 *     <li>动态注入属性值
 *     <li>自定义作用域
 * </ol>
 *
 * @author xzy
 * @date 2023/7/4  21:58
 */
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 动态修改Bean定义的属性值
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("exampleBean");
        beanDefinition.getPropertyValues().add("propertyName", "newValue");

        // 替换Bean的实现类
        beanDefinition.setBeanClassName("com.example.NewImplementation");

        // 根据条件移除或添加Bean的定义
        if (shouldRemove(beanFactory)) {
            if (beanFactory instanceof DefaultListableBeanFactory) {
                DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) beanFactory;
                dbf.removeBeanDefinition("beanToRemove");
            }
        }
        if (shouldRegister(beanFactory)) {
            beanFactory.registerSingleton("newBean", new CustomBean());
        }

        // 动态注入属性值
        ExampleBean exampleBean = beanFactory.getBean(ExampleBean.class);
        exampleBean.setDynamicProperty("dynamicValue");

        // 自定义作用域
        ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(beanDefinition);
        scopeMetadata.setScopeName("customScope");
    }


    private boolean shouldRemove(ConfigurableListableBeanFactory beanFactory) {
        // 条件判断...
        return false;
    }

    private boolean shouldRegister(ConfigurableListableBeanFactory beanFactory) {
        // 条件判断...
        return false;
    }
}
